package com.codemonkey.lq.common.util;

import java.io.PrintWriter;
import java.io.StringWriter;

// 这个名字是深受guava的毒害！
public final class ThrowableHelper {

	/**
	 * from httl项目的ClassUtils类中
	 * @param e
	 * @return
	 */
	public static String toString(Throwable e) {
		StringWriter w = new StringWriter();
		PrintWriter p = new PrintWriter(w);
		p.print(e.getClass().getName() + ": ");
		if (e.getMessage() != null) {
			p.print(e.getMessage() + "\n");
		}
		p.println();
		try {
			e.printStackTrace(p);
			return w.toString();
		} finally {
			p.close();
		}
	}

	/**
	 * 有时候为了应对强制异常检测的问题, 我们就需要将原本的异常使用RuntimeException进行包装. <br>
	 * 所以我们提供了这个方法来进行解包.
	 * @param throwable
	 * @return
	 */
	public static Throwable unwrap(Throwable throwable) {
		// 参见guava中的 Throwables.getRootCause
		// 参见 Mybatis中的 ExceptionFactory
		/* 可能被封装多次 */
		while (throwable.getClass().equals(RuntimeException.class) && throwable.getCause() != null) {
			throwable = throwable.getCause();
		}

		return throwable;
	}

	/**
	 * 是否被指定的类(必须是直接调用类, 非继承链上的)调用
	 * @param specialClass
	 * @return
	 */
	public static boolean isCalledBySpecialClass(Class<?> specialClass) {
		if (null == specialClass) {
			return false;
		}

		StackTraceElement stackElements[] = Thread.currentThread().getStackTrace();
		if (null == stackElements) {
			return false;
		}

		for (int i = stackElements.length - 1; i >= 0; i--) {
			final StackTraceElement stackTraceElement = stackElements[i];
			if (stackTraceElement.getClassName().equals(specialClass.getName())) {
				return true;
			}
		}

		return false;

	}
}
